package cn.sh.user.service.impl;

import cn.sh.basic.domain.dto.SendEmailDto;
import cn.sh.basic.domain.dto.SendSmsDto;
import cn.sh.basic.exception.CustomException;
import cn.sh.basic.util.MD5Utils;
import cn.sh.basic.util.StrUtils;
import cn.sh.user.domain.Logininfo;
import cn.sh.user.domain.User;
import cn.sh.user.mapper.LogininfoMapper;
import cn.sh.user.mapper.UserMapper;
import cn.sh.user.service.IUserService;
import cn.sh.basic.service.impl.BaseServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.Date;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author sh
 * @since 2022-08-09
 */
@Service
public class UserServiceImpl extends BaseServiceImpl<User> implements IUserService {
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private LogininfoMapper logininfoMapper;

    @Override
    @Transactional
    public void phoneRegister(SendSmsDto dto) {
        //        1. 非空校验
        if(StringUtils.isEmpty(dto.getMobile()) || StringUtils.isEmpty(dto.getPassword()) ||
                StringUtils.isEmpty(dto.getConfirmPassword())){
            throw new CustomException("参数异常!");
        }
//        2. 密码一致性校验
        if(!dto.getPassword().equals(dto.getConfirmPassword())){
            throw new CustomException("密码不一致");
        }
//        3. 用前端传递的手机号拼接业务键，去redis中查询短信验证码
        String smsCodeKey = dto.getMobile()+":register";
        Object smsCodeValue = redisTemplate.opsForValue().get(smsCodeKey);
//        1. 如果查不到，返回自定义异常，短信验证码过期了
        if(smsCodeValue == null){
            throw new CustomException("短信验证码已过期");
        }
//        4. 查到就和前端传递的验证码进行比对
        String smsCode = smsCodeValue.toString().split(":")[0];
        //        1. 不一致，返回自定义异常，验证码错误
        if(!smsCode.equals(dto.getSmsCode())){
            throw new CustomException("短信验证码错误");
        }
//        5. 生成盐值随机字符串（32位）保留
        String salt = StrUtils.getComplexRandomString(32);
//        6. 使用MD5工具类加密密码（密码需要拼接盐值一起加密）
        String md5PassWord = MD5Utils.encrypByMd5(dto.getPassword() + salt);
//        7. 构建user和login_info对象，初始化参数
        User user = initUser(dto.getMobile(),salt,md5PassWord);
        Logininfo logininfo =  user2LoginInfo(user);
//        8. 先保存login_info，获取自增id
        logininfoMapper.add(logininfo);
        //把logininfo保存后的自增id给到user中
        user.setLogininfoId(logininfo.getId());
        //        9. 再保存user
        userMapper.add(user);
    }

    @Override
    public void emailRegister(SendEmailDto edto) {
        //        1. 非空校验
        if(StringUtils.isEmpty(edto.getMobile()) || StringUtils.isEmpty(edto.getPassword()) ||
                StringUtils.isEmpty(edto.getConfirmPassword())){
            throw new CustomException("参数异常!");
        }
//        2. 密码一致性校验
        if(!edto.getPassword().equals(edto.getConfirmPassword())){
            throw new CustomException("密码不一致");
        }
//        3. 用前端传递的手机号拼接业务键，去redis中查询短信验证码
        String emailCodeKey = edto.getMobile()+":register";
        Object emailCodeValue = redisTemplate.opsForValue().get(emailCodeKey);
//        1. 如果查不到，返回自定义异常，短信验证码过期了
        if(emailCodeValue == null){
            throw new CustomException("邮箱验证码已过期");
        }
//        4. 查到就和前端传递的验证码进行比对
        String emailCode = emailCodeValue.toString().split(":")[0];
        //        1. 不一致，返回自定义异常，验证码错误
        if(!emailCode.equals(edto.getEmailCode())){
            throw new CustomException("邮箱验证码错误");
        }
//        5. 生成盐值随机字符串（32位）保留
        String salt = StrUtils.getComplexRandomString(32);
//        6. 使用MD5工具类加密密码（密码需要拼接盐值一起加密）
        String md5PassWord = MD5Utils.encrypByMd5(edto.getPassword() + salt);
//        7. 构建user和login_info对象，初始化参数
        User user = intemail(edto.getMobile(),salt,md5PassWord);
        Logininfo logininfo =  user2LoginInfo(user);
//        8. 先保存login_info，获取自增id
        logininfoMapper.add(logininfo);
        //把logininfo保存后的自增id给到user中
        user.setLogininfoId(logininfo.getId());
        //        9. 再保存user
        userMapper.add(user);
    }

    private Logininfo user2LoginInfo(User user) {
        Logininfo logininfo = new Logininfo();
        BeanUtils.copyProperties(user,logininfo);
        //初始化参数type 1主站用户
        logininfo.setType(1);
        //初始化参数disabl 1 可用
        logininfo.setDisable(1);
        return logininfo;
    }

    private User initUser(String mobile, String salt, String md5PassWord) {
        User user = new User();
        user.setUsername(mobile);
        user.setPhone(mobile);
        user.setSalt(salt);
        user.setPassword(md5PassWord);
        user.setState(1);
        user.setCreatetime(new Date());
        return user;
    }
    private User intemail(String mobile, String salt, String md5PassWord){
        User user = new User();
        user.setUsername(mobile);
        user.setEmail(mobile);
        user.setSalt(salt);
        user.setPassword(md5PassWord);
        user.setState(1);
        user.setCreatetime(new Date());
        return user;
    }

}
